package ui.swing.table.renderer;

import java.awt.Color;
import java.awt.Component;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.util.StringTokenizer;

import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;

//Custom cell renderer used to align strings that contain tab characters into
//visual columns
public class TabListCellRenderer extends JLabel implements ListCellRenderer {

	private static final long serialVersionUID = -2766850803087471848L;

	protected static Border m_noFocusBorder = new EmptyBorder(1, 1, 1, 1);;

	protected FontMetrics m_fm = null;
	protected Insets m_insets = null; // new Insets(0, 0, 0, 0);
	protected int m_defaultTab = 50;
	protected int[] m_tabs = null;

	public TabListCellRenderer() {
		setOpaque(true);
		setBorder(m_noFocusBorder);		
	}

	public Component getListCellRendererComponent(JList list, Object value,
			int index, boolean isSelected, boolean cellHasFocus) {

		setText(value.toString());

		setBackground(isSelected ? list.getSelectionBackground() : list
				.getBackground());
		setForeground(isSelected ? list.getSelectionForeground() : list
				.getForeground());

		setFont(list.getFont());
		setBorder((cellHasFocus ? UIManager
				.getBorder("List.focusCellHighlightBorder") : m_noFocusBorder));
		return this;
	}

	public void setDefaultTab(int defaultTab) {
		m_defaultTab = defaultTab;
	}

	public void setTabs(int[] tabs) {
		m_tabs = tabs;
	}

	// Method responsible for rendering each cell the getTab() method is used
	// to retrieve the number of pixels corresponding to a given tab index
	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g); // 注意啊，都要先画好"本来的"

		Color colorRetainer = g.getColor();
		m_fm = g.getFontMetrics();

		// 背景和边框
		g.setColor(getBackground());
		g.fillRect(0, 0, getWidth(), getHeight());
		getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight());

		// 前景
		g.setColor(getForeground());
		g.setFont(getFont());
		m_insets = getInsets();
		int x = m_insets.left;
		int y = m_insets.top + m_fm.getAscent();

		StringTokenizer st = new StringTokenizer(getText(), "\t");
		while (st.hasMoreTokens()) {
			String sNext = st.nextToken();
			g.drawString(sNext, x, y);
			x += m_fm.stringWidth(sNext);

			if (!st.hasMoreTokens())
				break;
			int index = 0;
			while (x >= getTab(index))
				index++;
			x = getTab(index);
		}

		g.setColor(colorRetainer);
	}

	// Method to calculate the distance to use corresponding to a given tab
	// index
	private int getTab(int index) {
		if (m_tabs == null) {
			return m_defaultTab * index;
		}

		int len = m_tabs.length;
		if (index >= 0 && index < len)
			return m_tabs[index];

		return m_tabs[len - 1] + m_defaultTab * (index - len + 1);
	}

}
